package com.css.fxfzfxqh.base.upload;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.css.fxfzfxqh.base.attachment.entity.AttachmentInfoEntity;
import com.css.fxfzfxqh.base.attachment.service.AttachmentInfoService;
import com.css.fxfzfxqh.base.response.RestResponse;
import com.css.fxfzfxqh.modules.largeScreen.entity.KeynoteData;
import com.css.fxfzfxqh.modules.util.hypergraph.service.HypergraphService;
import com.css.fxfzfxqh.util.PlatformObjectUtils;
import com.css.fxfzfxqh.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author Dbj
 * @date 2022年08月01日  16:40
 * @desc 附件的上传和下载
 */
@RestController
@Slf4j
@RequestMapping("/attachment")
public class AttachmentController {

    @Value("${image.localDir}")
    private String localDir;

    @Autowired
    private AttachmentInfoService attachmentInfoService;
    @Autowired
    private HypergraphService hypergraphService;

    /**
     * 文件上传
     */
    @PostMapping("/uploadFile")
    public RestResponse uploadFile(List<MultipartFile> file) {
        for (MultipartFile multipartFile : file) {
            if (multipartFile.isEmpty()) {
                return RestResponse.fail("不允许上传空文件");
            }
        }
        RestResponse restResponse = null;
        if (file.size() == 0) {
            restResponse = RestResponse.fail("上传失败，请选择文件");
            return restResponse;
        }
        if (file.size() > 50) {
            restResponse = RestResponse.fail("上传失败，请将上传的文件控制在50个以内");
            return restResponse;
        }
        List<String> attachmentInfoIdList = new ArrayList<String>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        for (int i = 0; i < file.size(); i++) {
            if (!file.get(i).isEmpty()) {
                MultipartFile multipartFile = file.get(i);
                try {
                    //获取文件名称
                    String fileName = multipartFile.getOriginalFilename();
                    //获取文件上传的本地路径
                    String dateDir = new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = localDir + dateDir;
                    //构建文件
                    assert fileName != null;
                    //上传文件
                    String realFileName = uploadFile(fileName, savePath, multipartFile);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildAttachment(fileName, dateDir, realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                    restResponse = RestResponse.fail("文件上传失败");
                    return restResponse;
                }
            }
        }
        int flag = 0;
        //保存附件到数据库
        if (ObjectUtils.isNotEmpty(attachmentInfoEntities)) {
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        //上传成功返回文件名用于业务实体保存
        if (flag == 1) {
            restResponse = RestResponse.succeed(attachmentInfoEntities);
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }

    /**
     * 文件上传
     */
    @PostMapping("/fileUpload")
    @Transactional(rollbackFor = Exception.class)
    public RestResponse uploadFile(@RequestBody  Map<String,String> paramMap){
        String attachId = paramMap.get("attachId");
        String type = paramMap.get("type");
        AttachmentInfoEntity attach = attachmentInfoService.getAttach(attachId);
        RestResponse restResponse = RestResponse.succeed();
        //上传成功返回文件名用于业务实体保存
        if(buildAndSaveData(type,attach)==1){
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }

    private Integer buildAndSaveData(String type,AttachmentInfoEntity attach){
        ImportParams params = new ImportParams();
//        params.setHeadRows(2);
//        params.setTitleRows(1);
        params.setNeedVerify(false);
        int flag = 0;
        if("全国重点目标数据".equals(type)){
            ExcelImportResult<KeynoteData> result = ExcelImportUtil.importExcelMore(new File(attach.getFileDirId()+ File.separator+attach.getAttachPath()), KeynoteData.class, params);
            List<KeynoteData> list = result.getList();
            if(PlatformObjectUtils.isEmpty(list)){
                throw  new RuntimeException("上传表中无数据，请重新上传");
            }
            //保存附件到数据库
            if(ObjectUtils.isNotEmpty(list)){
                flag = attachmentInfoService.saveKeynoteData(list);
            }
        }
        return flag;
    }

    /**
     * shp文件上传
     */
    @PostMapping("/uploadShpFile")
    public RestResponse uploadShpFile(List<MultipartFile> file) {
        for (MultipartFile multipartFile : file) {
            if (multipartFile.isEmpty()) {
                return RestResponse.fail("不允许上传空文件");
            }
        }
        RestResponse restResponse = null;
        if (file.size() == 0) {
            restResponse = RestResponse.fail("上传失败，请选择文件");
            return restResponse;
        }
        if (file.size() > 50) {
            restResponse = RestResponse.fail("上传失败，请将上传的文件控制在50个以内");
            return restResponse;
        }
        List<String> attachmentInfoIdList = new ArrayList<>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        String currTime = System.currentTimeMillis() + "";
        for (int i = 0; i < file.size(); i++) {
            if (!file.get(i).isEmpty()) {
                MultipartFile multipartFile = file.get(i);
                try {
                    //获取文件名称
                    String fileName = multipartFile.getOriginalFilename();
                    //获取文件上传的本地路径
                    String dateDir = File.separator + "shape" + File.separator + new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = localDir + File.separator + dateDir;
                    //构建文件
                    assert fileName != null;
                    fileName = getDateFormatFileName(fileName);
                    //上传文件
                    String realFileName = uploadFile(fileName, savePath, multipartFile, currTime);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildAttachment(fileName, dateDir, realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                    restResponse = RestResponse.fail("文件上传失败");
                    return restResponse;
                }
            }
        }
        int flag = 0;
        //保存附件到数据库
        if (ObjectUtils.isNotEmpty(attachmentInfoEntities)) {
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        //上传成功返回文件名用于业务实体保存
        if (flag == 1) {
            restResponse = RestResponse.succeed(attachmentInfoEntities);
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }

    private static String getDateFormatFileName(String fileName) {
        return FileUtil.getPrefix(fileName) + "_" + DateUtil.format(new Date(), "yyyyMMddHHmm") + "." + FileUtil.getSuffix(fileName);
    }

    private String uploadFile(String fileName, String savePath, MultipartFile multipartFile, String currTime) throws IOException {
        // 获取文件的后缀名
        assert fileName != null;
        String preFileName = fileName.substring(0, fileName.lastIndexOf("."));
        // .jpg  .pdf  .txt  .docs
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        // 拼文件名  真实的文件名称
        String realFileName = preFileName + "_" + currTime + fileType;
        //判断文件夹是否存在如果不存在则创建
        if (!new File(savePath).exists()) {
            new File(savePath).mkdirs();
        }
        File file = new File(savePath, realFileName);
        multipartFile.transferTo(file);
        return realFileName;
    }

    private String uploadFile(String fileName, String savePath, MultipartFile multipartFile) throws IOException {
        // 获取文件的后缀名
        assert fileName != null;
        String preFileName = fileName.substring(0, fileName.lastIndexOf("."));
        // .jpg  .pdf  .txt  .docs
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        // 拼文件名  真实的文件名称
        String realFileName = preFileName + "_" + System.currentTimeMillis() + fileType;
        //判断文件夹是否存在如果不存在则创建
        if (!new File(savePath).exists()) {
            new File(savePath).mkdirs();
        }
        File file = new File(savePath, realFileName);
        multipartFile.transferTo(file);
        return realFileName;
    }

    private AttachmentInfoEntity buildAttachment(String fileName, String dateDir, String realFileName) {
        AttachmentInfoEntity attachmentInfoEntity = new AttachmentInfoEntity();
        attachmentInfoEntity.setAttachId(StringUtils.buildPrimaryId());
        attachmentInfoEntity.setAttachName(fileName);
        attachmentInfoEntity.setAttachPath(dateDir + "/" + realFileName);
        attachmentInfoEntity.setFileDirId(localDir);
        attachmentInfoEntity.setIsValid("1");
        attachmentInfoEntity.setIsCompleted("1");
        return attachmentInfoEntity;
    }

    @PostMapping(value = "/downloadExcel", produces = "text/html;charset=UTF-8")
    public void downloadExcel1(@RequestBody Map<String,String> paramMap, HttpServletResponse response) {
        String fileName = paramMap.get("fileName");
        log.info("入参: 模板名全称:{}", fileName);
        try {
            //请求头的模板名为中文
            String file_name = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-disposition", "attachment;fileName=" + file_name);
            response.setContentType("application/x-download");
            //获取文件的路径
            String path = getClass().getResource("/template/" + fileName).getPath();
            //路径名转换中文
            String filePath = URLDecoder.decode(path, "utf-8");
            FileInputStream inputStream = new FileInputStream(filePath);
            OutputStream outputStream = response.getOutputStream();
            byte[] bytes = new byte[65536];
            int len;
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
            }
            outputStream.flush();
            outputStream.close();
            inputStream.close();
            log.info(fileName + ": 模板下载完成");
        } catch (Exception e) {
            e.printStackTrace();
            log.error(fileName + ":" + e);
        }
    }
    /**
     * 文件下载
     *
     * @param attachId 附件id
     */
    @GetMapping(value = "/downLoadFile")
    public void downloadFile(@RequestParam("attachId") String attachId) {
        OutputStream os = null;
        InputStream is = null;
        try {
            //根据id和文件名获取真实的放在磁盘上的文件
            AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(attachId);
            String attachPath = attachmentInfoEntity.getAttachPath();
            if (org.apache.commons.lang3.StringUtils.isNotBlank(attachPath)) {
                // 防乱码
//                    String name =
//                        new String(realFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                assert requestAttributes != null;
                HttpServletResponse response = requestAttributes.getResponse();
                assert response != null;
                response.reset();
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(attachmentInfoEntity.getAttachName(), "UTF-8") + "\"");
                // 跨域
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Method", "POST,GET");
                String name = localDir + attachPath;
                File file = new File(name);
                if (!file.exists()) {
                    file = new File(attachmentInfoEntity.getFileDirId() + attachPath);
                }
                is = new FileInputStream(file);

                // PrintWrite pw=response.getWriter();  或
                os = response.getOutputStream();
                int flag = 0;
                while ((flag = is.read()) != -1) {
                    os.write(flag);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (os != null) {
                    os.flush();
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 删除附件
     *
     * @param map
     * @return
     */
    @PostMapping("/deleteFile")
    public RestResponse deleteFile(@RequestBody Map<String, String> map) {
        RestResponse response = null;
        try {
            if (!PlatformObjectUtils.isEmpty(map)) {
                boolean res = attachmentInfoService.deleteFile(map);
                if (res) {
                    response = RestResponse.succeed("附件删除成功!");
                    response.setMessage("附件删除成功!");
                }

            } else {
                response = RestResponse.fail("附件删除失败! attachId为空!");
            }
        } catch (Exception e) {
            log.error("附件删除失败!", e);
            response = RestResponse.fail("附件删除失败!");
        }
        return response;
    }


    @GetMapping("/findFileById")
    public RestResponse findFileById(@RequestParam String attachId) {
        RestResponse response = null;
        try {
            AttachmentInfoEntity attach = attachmentInfoService.getAttach(attachId);
            response = RestResponse.succeed(attach);
        } catch (Exception e) {
            log.error("附件查询失败!", e);
            response = RestResponse.fail("附件查询失败!");
        }
        return response;
    }

    /**
     * 超图工作空间文件上传
     */
    @PostMapping("/uploadSmwuFile")
    public RestResponse uploadSmwuFile(List<MultipartFile> file){
        RestResponse restResponse = null;
        if (file.size()==0) {
            restResponse = RestResponse.fail("上传失败，请选择文件");
            return restResponse;
        }
        if(file.size()>2){
            restResponse = RestResponse.fail("上传失败，请上传2个文件，包括.smwu文件和.udbx文件");
            return restResponse;
        }
        List<String> attachmentInfoIdList = new ArrayList<String>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        for(int i = 0;i<file.size();i++){
            if(file.get(i) != null){
                MultipartFile multipartFile = file.get(i);
                try {
                    //获取文件名称
                    String fileName=multipartFile.getOriginalFilename();
                    //获取文件上传的本地路径
                    String dateDir = new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = localDir + dateDir;
                    //获取新的交通网络分析服务版本号
                    String version = hypergraphService.getNetworkanalystVersionCode();
                    String folder = "/超图工作空间数据编号" + version;
                    savePath += folder;
                    //构建文件
                    assert fileName != null;
                    //上传文件
                    String realFileName = uploadSmwuFile(fileName,savePath,multipartFile);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildAttachmentSmwu(fileName,dateDir,folder,realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                    restResponse = RestResponse.fail("文件上传失败");
                    return restResponse;
                }
            }
        }
        int flag = 0;
        //保存附件到数据库
        if(ObjectUtils.isNotEmpty(attachmentInfoEntities)){
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        //上传成功返回文件名用于业务实体保存
        if(flag==1){
            restResponse = RestResponse.succeed(attachmentInfoEntities);
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }

    private String uploadSmwuFile(String fileName, String savePath, MultipartFile multipartFile) throws IOException {
        // 获取文件的后缀名
        assert fileName != null;
        // 拼文件名  真实的文件名称
        String realFileName = fileName;
        //判断文件夹是否存在如果不存在则创建
        if (!new File(savePath).exists()) {
            new File(savePath).mkdirs();
        }
        File file = new File(savePath, realFileName);
        multipartFile.transferTo(file);
        return realFileName;
    }

    private AttachmentInfoEntity buildAttachmentSmwu(String fileName, String dateDir, String folder, String realFileName) {
        AttachmentInfoEntity attachmentInfoEntity = new AttachmentInfoEntity();
        attachmentInfoEntity.setAttachId(StringUtils.buildPrimaryId());
        attachmentInfoEntity.setAttachName(fileName);
        attachmentInfoEntity.setAttachPath(dateDir + folder + "/" + realFileName);
        attachmentInfoEntity.setFileDirId(localDir);
        attachmentInfoEntity.setIsValid("1");
        attachmentInfoEntity.setIsCompleted("1");
        return attachmentInfoEntity;
    }
}
